package org.road0329.dlt698.buss;

import com.alibaba.fastjson2.JSON;
import org.road0329.dlt698.DataUtils;
import org.road0329.dlt698.ReverseByteArrayInputStream;
import org.road0329.dlt698.axdr.Apdu;
import org.road0329.dlt698.axdr.M698pdu;
import org.road0329.dlt698.bean.FrameData;
import org.road0329.dlt698.build.*;
import org.road0329.dlt698.opt.*;
import org.road0329.dlt698.sessionlayer.hdlc.HdlcFrame;
import org.road0329.dlt698.tools.ResultCode;


public class Dlt698 {
    private static Dlt698 instance = null;
    private Dlt698() {
    }
    public static Dlt698 getInstance() {
        if (instance == null) {
            instance = new Dlt698();
        }
        return instance;
    }
    public void buildFrame(Option param) throws Exception {
        String data = "";
        LinkOption linkOpt = param.getLinkOption();
        RequestOption requestOption = param.getRequestOption();
        if (linkOpt == null || requestOption == null) {
            data = "link_option or requestOption not allow empty";
            param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
            return;
        }
        if (linkOpt.getServerAddress() == null || linkOpt.getClientAddress() == null) {
            data = "server_address or client_address not allow empty";
            param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
            return;
        } else {
            if (linkOpt.getServerAddress().length() == 0 || linkOpt.getServerAddress().length() != 12) {
                data = "server_address length is Illegal";
                param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                return;
            }
            if (linkOpt.getClientAddress().length() == 0 || linkOpt.getClientAddress().length() != 2) {
                data = "client_address length is Illegal";
                param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                return;
            }
        }
        if (requestOption.getRequestMode() != M698pdu.Choice.GET_REQUEST.getValue()
                && requestOption.getRequestMode() != M698pdu.Choice.SET_REQUEST.getValue()
                && requestOption.getRequestMode() != M698pdu.Choice.ACTION_REQUEST.getValue()
                && requestOption.getRequestMode() != M698pdu.Choice.CONNECT_REQUEST.getValue()
                && requestOption.getRequestMode() != M698pdu.Choice.PROXY_REQUEST.getValue()
                && requestOption.getRequestMode() != M698pdu.Choice.SECURITY_REQUEST.getValue()) {
            data = "getRequestMode() length is Illegal";
            param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
            return;
        } else {
            if (requestOption.getRequestMode() == M698pdu.Choice.GET_REQUEST.getValue()) {
                GetRequestOption getOpt = (GetRequestOption) requestOption.getRequest();
                if (getOpt == null || getOpt.getGetOption() == null) {
                    data = "get request not allow empty";
                    param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                } else {
                    GenernalCallBack result = GetRequestBuilder.buildGetRequest(getOpt, linkOpt, requestOption);
                    if (result.getResultCode() == ResultCode.SUCCESS.getCode()) {
                        param.setSuccess(result);
                    } else {
                        param.setError(result);
                    }
                }
            } else if (requestOption.getRequestMode() == M698pdu.Choice.SET_REQUEST.getValue()) {
                SetRequestOption setOpt = (SetRequestOption) requestOption.getRequest();
                if (setOpt == null || setOpt.getSetOption() == null) {
                    data = "set request not allow empty";
                    param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                } else {
                    GenernalCallBack result = SetRequestBuilder.buildSetRequest(setOpt, linkOpt, requestOption);
                    if (result.getResultCode() == ResultCode.SUCCESS.getCode()) {
                        param.setSuccess(result);
                    } else {
                        param.setError(result);
                    }
                }
            } else if (requestOption.getRequestMode() == M698pdu.Choice.ACTION_REQUEST.getValue()) {
                ActionRequestOption actionOpt = (ActionRequestOption) requestOption.getRequest();
                if (actionOpt == null || actionOpt.getActionOption() == null) {
                    data = "action request not allow empty";
                    param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                    return;
                } else {
                    GenernalCallBack result = ActionRequestBuilder.buildActionRequest(actionOpt, linkOpt, requestOption);
                    if (result.getResultCode() == ResultCode.SUCCESS.getCode()) {
                        param.setSuccess(result);
                    } else {
                        param.setError(result);
                    }
                }
            } else if (requestOption.getRequestMode() == M698pdu.Choice.CONNECT_REQUEST.getValue()) {
                ConnectRequestOption connectOpt = (ConnectRequestOption) requestOption.getRequest();
                if (connectOpt == null) {
                    data = "connect request not allow empty";
                    param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                    return;
                } else {
                   GenernalCallBack result = ConnectRequestBuilder.buildConnectRequest(connectOpt, linkOpt, requestOption);
                    if (result.getResultCode() == ResultCode.SUCCESS.getCode()) {
                        param.setSuccess(result);
                    } else {
                        param.setError(result);
                    }
                }
            } else if (requestOption.getRequestMode() == M698pdu.Choice.PROXY_REQUEST.getValue()) {
                ProxyRequestOption proxyRequestOption = (ProxyRequestOption) requestOption.getRequest();
                if (proxyRequestOption == null) {
                    data = "proxy request not allow empty";
                    param.setError(new GenernalCallBack(ResultCode.ILLEGAL_ERROR.getCode(), data));
                    return;
                } else {
                    GenernalCallBack result = ProxyRequestBuilder.buildProxyRequest(proxyRequestOption, linkOpt, requestOption);
                    if (result.getResultCode() == ResultCode.SUCCESS.getCode()) {
                        param.setSuccess(result);
                    } else {
                        param.setError(result);
                    }
                }
            }
        }
    }
    public FrameData parseLinkFrame(String frame) throws Exception {
        FrameData frameData = new FrameData();
        int lenPractical = frame.length() - 4;
        String len_first = frame.substring(2, 4);
        String len_second = frame.substring(4, 6);
        int len = Integer.parseInt(len_second + len_first, 16);
        if (len * 2 != lenPractical) {
            frameData.setCode(ResultCode.ILLEGAL_ERROR.getCode());
            frameData.setData( "frame length is illegal");
            return frameData;
        }
        String appFrame;
        System.out.println(frame);
        ReverseByteArrayInputStream dataInputStream = new ReverseByteArrayInputStream(DataUtils.hexToBytes(frame.toString()));
        HdlcFrame hdlcFrame;
        try {
            hdlcFrame = new HdlcFrame().decode(dataInputStream);
            if (hdlcFrame.isSegmented()) {
                String s = Integer.toHexString(hdlcFrame.getSegFrameType() | hdlcFrame.getSegFrameXh());
                while (s.length() < 4) {
                    s = s.substring(0, 1) + "0" + s.substring(1);
                }
                appFrame = s;
            } else {
                byte[] field = hdlcFrame.getInformationField();
                appFrame = DataUtils.toHexString(field, 1, 0);
            }
        } catch (Exception e) {
            frameData.setCode(ResultCode.ILLEGAL_ERROR.getCode());
            frameData.setData( "frame parse failed");
            return frameData;
        }
        return parseAppFrame(appFrame);
    }
    public FrameData parseAppFrame(String frame) throws Exception {
        FrameData frameData = new FrameData();
        if (frame == null) {
            frameData.setCode(ResultCode.EMPTY_ERROR.getCode());
            frameData.setData("frame is mot allow empty");
            return frameData;
        }
        Apdu apdu = Apdu.getInstance().decode(DataUtils.hexToBytes(frame));
        frameData.setCode(ResultCode.SUCCESS.getCode());
        frameData.setData(apdu.getM698pdu());
        return frameData;
    }

    public void parse(ParseOption option) throws Exception {
        String frame = option.getFrame();
        FrameData frameData = new FrameData();
        if (frame == null || frame.length() % 2 != 0) {
            frameData.setCode(ResultCode.ILLEGAL_ERROR.getCode());
            frameData.setData("frame param is illegal or empty");
            option.setResult(new ParseCallBack(JSON.toJSONString(frameData)));
        }
        if (frame.startsWith("68") && frame.endsWith("16")) {
            frameData = parseLinkFrame(frame);
            option.setResult(new ParseCallBack(JSON.toJSONString(frameData)));
        } else {
            option.setResult(new ParseCallBack(JSON.toJSONString(parseAppFrame(frame.toString()))));
        }
    }
}
